<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />

    <title></title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.js"></script>

    <script>
        require.config({
            paths: {
                vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/',
            },
        });
        window.MonacoEnvironment = {
            getWorkerUrl: function (workerId, label) {
                return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
            self.MonacoEnvironment = {
              baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/'
            };
            importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/base/worker/workerMain.js');`)}`;
            },
        };
        require(['vs/editor/editor.main'], function () {

        });
    </script>
</head>
<style>
    #app {
        display: flex;
        flex-direction: column;
        height: 100vh;
    }

    .editor-wrapper {
        flex: 1;
        display: flex;
        flex-wrap: wrap;

    }

    #monaco-editor-wrapper,
    #monaco-editor-towrapper {
        flex: 1;
        height: 50%;
        width: 50%;
    }

    #monaco-editor-fun {
        width: 100%;
        height: 30%;
    }

    #select-tag {
        display: flex;
        flex-wrap: wrap;
        margin-top: 10px;
    }

    .list-item {
        border: 1px solid #FFE0EB;
        padding: 4px 10px;
        margin: 0 10px 10px 0;
        border-radius: 4px;
        cursor: pointer;
        font-size: 13px;
    }

    .list-item-active {
        background: #FFE0EB;
    }

    .button-wrapper {
        width: 100%;
    }

    button {
        background: transparent;
        border: 1px solid #FFE0EB;
    }
</style>

<body>
    <div id="app">
        <div>
            <input id="input-value" type="text" placeholder="请输入字符串" />
            <button id="add-button">添加转换方法</button>
            <div id="select-tag">
            </div>
        </div>


        <div class="editor-wrapper">
            <div id="monaco-editor-fun"></div>
            <div class="button-wrapper">
                <button id="transform-button">转换</button>
            </div>

            <div id="monaco-editor-wrapper"></div>
            <div id="monaco-editor-towrapper"></div>
        </div>

    </div>
    <script>
        let mapValue = [{
            key: 'stringToSelect',
            name: '，字符串转select数据',
            value: '地铁，公交，外卖，快递，到店，团餐，票务，用车，在线订酒店，在线订火车票，在线订机票，其他',
            fun: function transformData(value) {
                let arr = []
                value.split("，").forEach((item) => {
                    arr.push({ label: item, value: 'item' })
                })
                return arr
            }
        }, {
            key: 'arraryToSelect',
            name: '二维数组转select数据',
            value: [['subway', '地铁'], ['bus', '公交']],
            fun: function transformData(value) {
                let arr = []
                value.forEach((item) => {
                    arr.push({ label: item[1], value: item[0] })
                })
                return arr
            }
        }, {
            key: 'routermenu',
            name: '提供路由基本信息生成添加菜单sql',
            value: [{
                cname: "'ccc'",
                path: "'/default/rule/release/manual/:rule_id'",
                component: "'default/rule/release/manual/'",
                name: "'manualRelease'",
                pid: 29
            }],
            fun: function transformData(value) {
                let getCurDate = () => {
                    let now = new Date();
                    let month = now.getMonth() + 1; // 注意月份是从0开始的，所以加1
                    let day = now.getDate();
                    let hour = now.getHours();
                    let minute = now.getMinutes();
                    let second = now.getSeconds();

                    // 如果需要两位数表示，可以填充前导0
                    month = month < 10 ? '0' + month : month;
                    day = day < 10 ? '0' + day : day;
                    hour = hour < 10 ? '0' + hour : hour;
                    minute = minute < 10 ? '0' + minute : minute;
                    second = second < 10 ? '0' + second : second;

                    return `${now.getFullYear()}-${month}-${day} ${hour}:${minute}:${second}`
                }
                let formatSql = (dat) => {
                    const {
                        id,
                        pid = "''",
                        name,
                        cname,
                        image = "''",
                        description = "''",
                        path,
                        component,
                        code = "''",
                        redirect = "''",
                        type = 0,
                        action_type = 1,
                        has_public = 0,
                        hide_privilege = 0,
                        hide_sidebar = 0,
                        has_show_box = 0,
                        can_select = 1,
                        hidden = 0,
                        keep_alive = 0,
                        icon = "''",
                        icon_selected = "''",
                        order_no = 0,
                        created_at = "'" + getCurDate() + "'",
                        updated_at = "'" + getCurDate() + "'",
                        deleted_at = "'1000-01-01 00:00:00'" } = dat
                    return `(${pid},${name},${cname},${image},${description},${path},${component},${code},${redirect},${type},${action_type},${has_public},${hide_privilege},${hide_sidebar},${has_show_box},${can_select},${hidden},${keep_alive},${icon},${icon_selected},${order_no},${created_at},${updated_at},${deleted_at})`
                }
                let getSql = (arr) => {
                    let str = ''
                    arr.forEach((item, index) => {
                        str += formatSql(item) + (index !== arr.length - 1 ? ',' : '')
                    })
                    let a = "INSERT INTO" +
                        " `menu` (" +
                        "`pid`, `name`, `cname`, `image`, `description`, `path`, `component`, `code`, `redirect`, `type`, `action_type`, `has_public`, `hide_privilege`, `hide_sidebar`, `has_show_box`, `can_select`, `hidden`, `keep_alive`, `icon`, `icon_selected`, `order_no`, `created_at`, `updated_at`, `deleted_at`" +
                        ")" +
                        "VALUES";
                    return a + str
                }
                return getSql(value)
            }
        }]
        // 初始tag列表
        let initDom = false
        // 当前tag选中
        let curAct = 'stringToSelect'
        let editorInstance = null
        let toInstance = null
        let toInstanceFun = null
        // 初始编辑器实例
        const initEditorInstance = () => {
            if (!editorInstance) {
                editorInstance = initEditor('monaco-editor-wrapper')
            }
            if (!toInstance) {
                toInstance = initEditor('monaco-editor-towrapper', { language: 'javascript' })
            }
            if (!toInstanceFun) {
                toInstanceFun = initEditor('monaco-editor-fun', { language: 'javascript' })
            }

            reLayout()
        }
        // 重新渲染编辑器
        const reLayout = () => {
            if (editorInstance) {
                editorInstance.layout();
            }
            if (toInstance) {
                toInstance.layout();
            }
            if (toInstanceFun) {
                toInstanceFun.layout();
            }
        }
        window.onload = function () {
            initEditorInstance()
            setViewModel({ funV: mapValue[0].fun, original: mapValue[0].value, modified: `` })
            transformFun()

            // 转换点击
            document.getElementById('transform-button').addEventListener('click', function () {
                transformFun()
            })
            // 新增tag
            document.getElementById('add-button').addEventListener('click', function () {
                let nameVal = document.getElementById('input-value').value
                if (nameVal) {
                    let isExist = mapValue.find(item => item.name === nameVal)
                    if (isExist) {
                        alert('该转换名已存在')
                        return
                    }
                    transformFun().then((re) => {
                        let value = editorInstance.getValue()
                        let funVal = toInstanceFun.getValue()
                        let addItemObj = {
                            key: 'custom-' + Math.random().toString(36).substring(2, 15),
                            name: nameVal || '自定义' + mapValue.length,
                            value: JSON.parse(value),
                            fun: funVal
                        }
                        mapValue.push(addItemObj)
                        addItem(addItemObj, document.querySelector('#select-tag'))
                    })


                } else {
                    alert('请输入转换名')

                }
            })
            forData("select-tag", mapValue)

        }
        const initEditor = (id, config = {}) => {
            return window.monaco.editor.create(document.getElementById(id), {
                theme: 'vs', // 编辑器主题：vs, hc-black, or vs-dark
                autoIndent: true, // 自动缩进
                originalEditable: true,
                language: 'json',
                formatOnType: true, // 在输入后自动格式化
                formatOnPaste: true, // 在粘贴后自动格式化
                wordWrap: 'on',
                diffCodeLens: false,
                ...config
            });
        }
        // 设置变化值
        const setViewModel = ({ funV, original, modified }) => {
            let tpmFunV = typeof funV === 'string' ? funV : `${funV}`
            funV && tpmFunV && (toInstanceFun.setValue(tpmFunV))
            original && editorInstance.setValue(JSON.stringify(original));
            modified && toInstance.setValue(modified)
            setTimeout(() => {
                toInstanceFun.getAction('editor.action.formatDocument').run();
                toInstance.getAction('editor.action.formatDocument').run();
                editorInstance.getAction('editor.action.formatDocument').run();
            }, 300)

        }
        // 转换
        const transformFun = function () {
            var value = editorInstance.getValue();
            let funVal = toInstanceFun.getValue()
            return new Promise((resolve, reject) => {
                try {
                    if (!funVal) return reject('函数不能为空')
                    eval(funVal)
                    if (typeof transformData !== 'function') return reject('函数不能为空')
                    let dat = transformData(JSON.parse(value))

                    setViewModel({ modified: typeof dat === "string" ? dat : JSON.stringify(dat) })
                    resolve('转换成功')
                } catch (error) {
                    console.error(error)
                    return reject(error)
                }
            })



        }



        const forData = (id, data) => {
            let listId = document.querySelector('#' + id)
            for (let i = 0; i < listId.childNodes.length; i++) {
                listId.childNodes[i].remove()
            }
            if (!initDom) {
                listId.addEventListener('click', (e) => {
                    if (e.target.getAttribute('class') !== 'list-item') return
                    setTagAct(e.target, listId)
                    let curTag = mapValue.find((item) => { return item.key === e.target.getAttribute('data-key') })
                    setViewModel({ funV: curTag.fun, original: curTag.value, modified: `` })
                    transformFun()
                })
            }
            initDom = true
            // 添加子元素
            for (let i = 0; i < data.length; i++) {
                addItem(data[i], listId)
            }
        }
        // 设置tag选中
        const setTagAct = (target, dom) => {
            dom.childNodes.forEach(item => {
                item.classList.remove('list-item-active')

            })
            let key = target.getAttribute('data-key')
            target.classList.add('list-item-active');
            curAct = key
        }
        // 新增tag
        const addItem = (obj, listId) => {
            let option = document.createElement('div');
            option.setAttribute('class', 'list-item');
            if (obj.key === curAct) {
                option.setAttribute('class', 'list-item list-item-active');
            }

            option.setAttribute('data-key', obj.key);
            option.innerText = obj.name;
            listId.appendChild(option);
        }

        window.addEventListener('resize', () => {
            reLayout()
        });
    </script>
</body>

</html>